import datetime
from django.conf import settings
from django.utils import timezone
from drf_yasg.utils import swagger_serializer_method
from rest_framework import serializers

from lab.device.models import AppointmentMaterial, Device, DeviceParams, File, Lab, Appointment, Material
from lab.user.models import ExtendedUser


class LabListSerializer(serializers.ModelSerializer):

    class Meta:
        model = Lab
        fields = (
            'id', 'name', 'pic', 'address', 'desc')

class DeviceListSerializer(serializers.ModelSerializer):
    lab_name = serializers.SerializerMethodField(read_only=True)
    occupied_time_slot = serializers.SerializerMethodField(read_only=True)
    params = serializers.SerializerMethodField(read_only=True)

    def get_params(self, obj):
        params = DeviceParams.objects.filter(device_id=obj.id).all()
        results = [{'name': param.param_name,'value':param.param_value} for param in params]
        return results

    def get_lab_name(self, obj):
        return Lab.objects.filter(id = obj.lab_id).first().name

    def get_occupied_time_slot(self, obj):
        return "11111000011111"
    
    class Meta:
        model = Device
        fields = (
            'id', 'name', 'lab_name', 'pic', 'model', 'desc', 'user_guide', 'status', 'attach_desc', 'attach_pic', 'occupied_time_slot', 'params', 'maintain_date', 'maintain_type')

class AppointmentMaterialSerializer(serializers.ModelSerializer):
    name = serializers.SerializerMethodField(read_only=True)
    unit = serializers.SerializerMethodField(read_only=True)

    def get_name(self, obj):
        return Material.objects.filter(id=obj.material_id).first().name
    
    def get_unit(self, obj):
        return Material.objects.filter(id=obj.material_id).first().unit
        
    class Meta:
        model = AppointmentMaterial
        fields = ['material_id', 'number', 'name', 'unit']

class AppointmentSerializer(serializers.ModelSerializer):
    materials = serializers.SerializerMethodField()
    device_name = serializers.SerializerMethodField()
    model = serializers.SerializerMethodField()
    user_name = serializers.SerializerMethodField()
    lab_address = serializers.SerializerMethodField()
    appointment_pic = serializers.SerializerMethodField()

    def get_materials(self, obj):
        materials = AppointmentMaterial.objects.filter(appointment_id=obj.id)
        return AppointmentMaterialSerializer(materials, many=True).data
    
    def get_device_name(self, obj):
        device = Device.objects.filter(id=obj.device_id).first()
        return device.name if device else None
    
    def get_model(self, obj):
        device = Device.objects.filter(id=obj.device_id).first()
        return device.model if device else None
    
    def get_user_name(self, obj):
        extended_user = ExtendedUser.objects.filter(id=obj.user_id).first()
        return extended_user.user.username if extended_user else None

    def get_lab_address(self, obj):
        device = Device.objects.filter(id=obj.device_id).first()
        lab = Lab.objects.filter(id=device.lab_id).first()
        return lab.address if lab else None
    
    def get_appointment_pic(self, obj):
        file = File.objects.filter(id=obj.appointment_pic_id).first()
        return settings.MEDIA_URL + file.file.name if file else None

    class Meta:
        model = Appointment
        fields = [
            'id',
            'order_number',
            'device_id',
            'appointment_date',
            'occupied_time_slot',
            'desc',
            'created_time',
            'updated_time',
            'status',
            'user_id',
            'appointment_pic_id',
            'materials',
            'reason',
            'device_name', 
            'model', 
            'user_name',
            'lab_address',
            'appointment_pic'
        ]
        read_only_fields = ['id', 'order_number', 'created_time', 'updated_time', 'status', 'user_id', 'reason', 'device_name', 'model', 'user_name']

class AppointmentWriteSerializer(serializers.ModelSerializer):
    materials = AppointmentMaterialSerializer(write_only=True, many=True, required=False)

    class Meta:
        model = Appointment
        fields = [
            'id',
            'order_number',
            'device_id',
            'appointment_date',
            'occupied_time_slot',
            'desc',
            'created_time',
            'updated_time',
            'status',
            'user_id',
            'appointment_pic_id',
            'materials',
            'reason'
        ]
        read_only_fields = ['id', 'order_number', 'created_time', 'updated_time', 'status', 'user_id', 'reason']

class MyAppointmentSerializer(serializers.ModelSerializer):
    lab_name = serializers.SerializerMethodField(read_only=True)
    lab_address = serializers.SerializerMethodField(read_only=True)
    device_name = serializers.SerializerMethodField(read_only=True)
    device_model = serializers.SerializerMethodField(read_only=True)
    appointment_date_timestamp = serializers.SerializerMethodField(read_only=True)

    def get_device_name(self, obj):
        if not self.context.get('device'):
            self.context['device'] = Device.objects.filter(id = obj.device_id).first()
        return self.context.get('device').name
    
    def get_device_model(self, obj):
        if not self.context.get('device'):
            self.context['device'] = Device.objects.filter(id = obj.device_id).first()
        return self.context.get('device').model
    
    def get_lab_name(self, obj):
        if not self.context.get('device'):
            self.context['device'] = Device.objects.filter(id = obj.device_id).first()
        if not self.context.get('lab'):
            self.context['lab'] = Lab.objects.filter(id = self.context.get('device').lab_id).first()
        return self.context.get('lab').name
    
    def get_lab_address(self, obj):
        if not self.context.get('device'):
            self.context['device'] = Device.objects.filter(id = obj.device_id).first()
        if not self.context.get('lab'):
            self.context['lab'] = Lab.objects.filter(id = self.context.get('device').lab_id).first()
        return self.context.get('lab').address
    
    def get_appointment_date_timestamp(self, obj):
        if obj.appointment_date:
            if isinstance(obj.appointment_date, datetime.date):
                # Combine date with midnight time to create a datetime object
                obj_date_time = datetime.datetime.combine(obj.appointment_date, datetime.datetime.min.time())
                return int(obj_date_time.timestamp()*1000)
            else:
                # If it's already a datetime object
                return int(obj.appointment_date.timestamp()*1000)
        return None

    class Meta:
        model = Appointment
        fields = [
            'id',
            'order_number',
            'device_id',
            'appointment_date',
            'occupied_time_slot',
            'created_time',
            'status',
            'lab_name',
            'device_name',
            'lab_address',
            'device_model',
            'appointment_date_timestamp'
        ]

class FileSerializer(serializers.ModelSerializer):
    class Meta:
        model = File
        fields = ('id', 'file')

class MaterialSerializer(serializers.ModelSerializer):

    class Meta:
        model = Material
        fields = ('id', 'name', 'unit')

class DeviceMaintenanceSerializer(serializers.ModelSerializer):

    class Meta:
        model = Device
        fields = ('maintain_date', 'maintain_type', 'status')